#!/usr/bin/env python
#encoding : utf-8

import sys
import os
from request import Request
from response import Response
from jinja2_template import tmpl_engine_config
from dispatcher import Dispatcher, HandlerNotFoundException,import_handler 
import logger

class RetValueError(Exception):pass
class ConfigureErrot(Exception):pass
responses = {}

class WsgiServer(object):
	def __init__(self, setting, url_config):
		# first step : init log
		log_config = getattr(setting, 'log_config', None)
		for l in log_config:
			l[1] = os.path.join(setting.project_home, l[1])
		logger.init_log(log_config)
		
		#second step : configure templates dir
		template_root = ""
		if hasattr(setting, 'template_config'):
			tc = setting.template_config
			default_engine = tc.get('default')
			if not default_engine:
				raise ConfigureError('template_config needs to set default engine')

			for engine, config_dict in tc.items():
				if engine == 'default':
					continue
				config_dict['default'] = (engine == default_engine)

				# handle absolute and relative path for template directory
				if isinstance(config_dict['template_root'], list):
					path_list = config_dict['template_root']
					for i, path in enumerate(path_list):
						path_list[i] = os.path.join(setting.project_home,
													path_list[i])
				else:
					config_dict['template_root'] = os.path.join(setting.project_home, config_dict['template_root'])

				tmpl_engine_config(engine, **config_dict)

			self._default_tmpl = (default_engine, tc[default_engine])
			template_root = tc[default_engine]['template_root']
			if isinstance(template_root, list):
				template_root = template_root[0]

		#third step : configure  the  relationship of url and its handler	
		self._dispatcher = Dispatcher(url_config)

		self._setting = setting

	def get_handler(self, path):
		handler, params = self._dispatcher.get_handler(path)
		if isinstance(params, dict):
			largs, kargs = (), params
		else:
			largs, kargs = params, {}

		return handler, largs, kargs

	def __call__(self, environ, start_response):
		request = None
		try:
			path = environ['PATH_INFO']
			request = Request(environ, self._setting)
			handler, largs, kargs = self.get_handler(path)
			response = handler(request, *largs, **kargs)
			if not isinstance(response, Response):
				raise RetValueError('handler(%s) should return a Response object' % handler.__name__)

		except Exception, e:
			if hasattr(self._setting, 'exception_handler'):
				eh = self._setting.exception_handler
				if callable(eh):
					exception_handler = eh
				elif isinstance(eh, str):
					try:
						exception_handler = import_handler(eh)
					except Exception, ex:
						e = ex
						exception_handler = self.exception_handler
			else:
				exception_handler = self.exception_handler
			response = exception_handler(e, request, environ)

		ct = response['content-type'].strip().lower()

		if ct.startswith('text') and ct.find('charset') == -1:
			if hasattr(self, '_default_tmpl'):
				default_charset = self._default_tmpl[1].get('output_encoding')
				if default_charset:
					response.set_charset(default_charset)

		try:
			status_text = responses[response.status_code][0]
		except KeyError:
			status_text = 'UNKNOWN STATUS CODE'

		status = '%s %s' % (str(response.status_code), status_text)
		headers = response.headers
		output = response.output()
		start_response(status, headers)
		return [output]

	def exception_handler(self, exception, request, environ):
		import traceback, sys 

		if isinstance(exception, HandlerNotFoundException):
			response = Response('', 303, {'Location' : '/'})
		else:
			response = Response('500 internal error', 500)

		return response

if __name__ == '__main__':
	pass
